/*
 * 前面两个示例并没有指定父kobject即parent成员，下面指定其parent成员
 */

#include <linux/device.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/sysfs.h>
#include <linux/kernel.h>
#include <linux/stat.h>
#include <linux/slab.h>
#include <linux/string.h>
 
#define ATTR_NAME "name"
#define ATTR_VALUE	"value"
 
struct my_object {
    struct kobject kobj;
    int value;
};
 
static struct my_object *m_obj1;
static struct my_object *m_obj2;
 
 
/**********************************************************/
//attrubute
 
static struct attribute m_attr_name = {
    .name = ATTR_NAME,
    .mode = S_IRWXUGO,
};
 
static struct attribute m_attr_value = {
    .name = ATTR_VALUE,
    .mode = S_IRWXUGO,
};
 
 
static struct attribute *m_attrs[] = {
    &m_attr_name,
    &m_attr_value,
    NULL,
 
};
 
/**********************************************************/
//sysfs_ops
 
static ssize_t kobj_attr_show(struct kobject *kobj, struct attribute *attr,
                              char *buf)
{
    ssize_t count = 0;
    struct my_object *mobj;
 
    printk("%s\n", __FUNCTION__);
 
    if (!strcmp(attr->name, ATTR_NAME)) {
        count = sprintf(buf, "%s\n", kobject_name(kobj) );
    } else if (!strcmp(attr->name, ATTR_VALUE)) {
        mobj = container_of(kobj, struct my_object, kobj);
        count = sprintf(buf, "%d\n", mobj->value);
    }
 
 
    return count;
}
 
static ssize_t kobj_attr_store(struct kobject *kobj, struct attribute *attr,
                               const char *buf, size_t count)
{
    struct my_object *mobj;
 
    printk("%s\n", __FUNCTION__);
 
    if (!strcmp(attr->name, ATTR_VALUE)) {
        mobj = container_of(kobj, struct my_object, kobj);
        sscanf(buf, "%d", &mobj->value);
    }
 
    return count;
}
 
 
static struct sysfs_ops m_sys_ops = {
    .show 	= kobj_attr_show,
    .store 	= kobj_attr_store,
};
 
/**********************************************************/
//kobj_type
 
void kobj_release(struct kobject *kobj)
{
    struct my_object *mobj = container_of(kobj, struct my_object, kobj);
    if (mobj) {
        //释放my_object内存
        kfree(mobj);
    }
    printk("%s\n", __FUNCTION__);
 
}
 
static struct kobj_type m_ktype = {
    .release = kobj_release,
    .sysfs_ops = &m_sys_ops,
    .default_attrs = m_attrs,
};
 
/**********************************************************/
static int __init kobj_init(void)
{
    int error = 0;
    //申请m_obj1内存
    m_obj1 = (struct my_object *)kzalloc(sizeof(struct my_object), GFP_KERNEL);
 
    if (!m_obj1) {
        error = -ENOMEM;
        goto out;
    }
    //申请m_obj2内存
    m_obj2 = (struct my_object *)kzalloc(sizeof(struct my_object), GFP_KERNEL);
 
    if (!m_obj2) {
        error = -ENOMEM;
        goto out1;
    }
 
    //初始化m_obj1的kobject
    error = kobject_init_and_add(&m_obj1->kobj, &m_ktype, NULL, "kobj_demo1");
    if (error) {
        goto out2;
    }
 
    初始化m_obj2的kobject，并指定其parent为m_obj1->kobj
    error = kobject_init_and_add(&m_obj2->kobj, &m_ktype, &m_obj1->kobj, "kobj_demo2");
    if (error) {
        goto out2;
    }
    //初始化value值
    m_obj1->value = 1;
    m_obj2->value = 2;
 
    printk("%s success.\n", __FUNCTION__);
 
    return 0;
out2:
    kfree(m_obj2);
out1:
    kfree(m_obj1);
out:
    printk("%s failed!\n", __FUNCTION__);
    return error;
}
 
static void __exit kobj_exit(void)
{
    //删除kobject
    kobject_del(&m_obj2->kobj);
    //使引用计数减1并调用kobj_type的release函数
    kobject_put(&m_obj2->kobj);
 
    kobject_del(&m_obj1->kobj);
    kobject_put(&m_obj1->kobj);
 
    printk("%s\n", __FUNCTION__);
}
 
 
module_init(kobj_init);
module_exit(kobj_exit);
 
MODULE_AUTHOR("tonny");
MODULE_DESCRIPTION("kobject demo");
MODULE_LICENSE("GPL"); 



